package com.tanovo.secure;

import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.tanovo.bo.ResultObject;
import com.tanovo.bo.Token;
import com.tanovo.bo.UserCore;
import com.tanovo.config.UserInfoContext;
import com.tanovo.constants.CodeConstants;
import com.tanovo.exception.ServiceException;
import com.tanovo.service.IAuthTokenService;
import com.tanovo.service.IResource;
import com.tanovo.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Map;

@Component
@Slf4j
public class AccessFilter extends ZuulFilter {
    @Autowired
    private IAuthTokenService iAuthTokenService;
    @Autowired
    private IUserService iUserService;
    @Autowired
    private IResource iResource;

    @Override
    public Object run() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        try {
            //打印request日志
            this.printRequestLog();
            HttpServletRequest request = requestContext.getRequest();
            //白名单接口直接放行
            String requestURI = request.getRequestURI();
            String clientId = request.getHeader("clientId");
            String companyId = request.getHeader("companyId");
            String token = request.getHeader("token");
            log.info("请求的token:{} ,clientId:{},companyId:{}", token, clientId, companyId);
            String realPath = this.getRealPath(requestURI);
            //获取无需校验的资源列表
            boolean noCheckFlag = iResource.checkNoTokenResourceList(realPath);
            // 取出token 判断合法性
            UserCore userCore = null;
            if (StringUtils.isNotBlank(token)) {
                userCore = iAuthTokenService.checkToken(token);
            }
            if (noCheckFlag) {
                requestContext.addZuulRequestHeader(UserInfoContext.KEY_USERINFO_IN_HTTP_HEADER, JSONObject.toJSONString(userCore));
                return null;
            }
            if (userCore == null) {
                throw new ServiceException(CodeConstants.NO_PERMISSION,"无效的token");
            }
            //设置核心参数
            userCore.setRequestURI(realPath);
            //判断请求的接口是不是需要登录才可以访问
            boolean loginFlag = iResource.checkLoginResourceList(realPath);
            if (loginFlag) {
                requestContext.addZuulRequestHeader(UserInfoContext.KEY_USERINFO_IN_HTTP_HEADER, JSONObject.toJSONString(userCore));
                return null;
            }
            boolean resourceFlag = iUserService.checkUserResouce(userCore);
            if (resourceFlag == false) {
                throw new ServiceException("权限不足");
            }
            requestContext.addZuulRequestHeader(UserInfoContext.KEY_USERINFO_IN_HTTP_HEADER, JSONObject.toJSONString(userCore));
        } catch (ServiceException e) {
            log.error("Accessfilter业务异常", e);
            ResultObject resultObject = new ResultObject();
            if(StringUtils.isNotBlank(e.getCode())){
                resultObject.setCode(e.getCode());
            }else {
                resultObject.setCode(CodeConstants.SERVICE_ERROR);
            }
            this.setRespon(requestContext, e,resultObject);
        } catch (Exception e) {
            log.error("Accessfilter运行时异常", e);
            ResultObject resultObject = new ResultObject();
            resultObject.setCode(CodeConstants.RUN_ERROR);
            this.setRespon(requestContext, e,resultObject);
        }

        return null;

    }

    private void setRespon(RequestContext requestContext, Exception e, ResultObject resultObject) {
        resultObject.setMessage(e.getMessage());
        requestContext.setResponseBody(JSONObject.toJSONString(resultObject));
        requestContext.getResponse().setContentType("application/json;charset=UTF-8");//设置返回响应体格式
        requestContext.setSendZuulResponse(false);
    }

    private void printRequestLog() throws Exception {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        InputStream in = request.getInputStream();
        String reqBbody = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
        log.info("requestMethod:{},requestUrl:{} ", request.getMethod(), request.getRequestURL().toString());
        String header = request.getHeader("Content-Type");
        if (StringUtils.isNotBlank(header) && !header.contains("multipart/form-data")) {
            log.info("requestBody:{}", reqBbody);
        }
        Map<String, String[]> map = request.getParameterMap();
        // 打印请求url参数
        if (map != null) {
            StringBuilder sb = new StringBuilder();
            sb.append("request parameters:\t");
            for (Map.Entry<String, String[]> entry : map.entrySet()) {
                sb.append("[" + entry.getKey() + "=" + printArray(entry.getValue()) + "]");
            }
            log.info("requestParameters:{}", sb);
        }
    }

    String printArray(String[] arr) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            sb.append(arr[i]);
            if (i < arr.length - 1) {
                sb.append(",");
            }
        }
        return sb.toString();
    }


    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    private String getRealPath(String uri) {
        int index = uri.indexOf("/", uri.indexOf("/") + 1);
        String path = uri.substring(index);//含"/"
        return path;
    }
}
